﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text.RegularExpressions;
using GalaSoft.MvvmLight;
using ProjectWizardManagement.Entity.Model;

namespace ProjectWizardManagementv1.ViewModels.Concrete
{
    public class FileExplorerViewModel : ViewModelBase
    {
        private readonly string _rootDirectory;
        private readonly List<ProjectFile> _modelFiles; 

        public ObservableCollection<ProjectFileViewModel> RootFiles { get; set; }

        public FileExplorerViewModel()
        {
            RootFiles = new ObservableCollection<ProjectFileViewModel>();
        }

        public FileExplorerViewModel(List<ProjectFile> rootFiles, string rootDirectory)
        {
            _rootDirectory = rootDirectory;
            _modelFiles = rootFiles;

            ProjectFileViewModel.ProjectDirectoryPath = _rootDirectory;

            RootFiles = new ObservableCollection<ProjectFileViewModel>();
            foreach(ProjectFile file in rootFiles)
            {
                var fileViewModel = new ProjectFileViewModel(file);
                RootFiles.Add(fileViewModel);
            }
        }

        public bool HasFileOrDirectory(string path)
        {
            path = path.Replace(_rootDirectory, "");
            string[] files = path.Split(new []{"\\"}, StringSplitOptions.RemoveEmptyEntries);

            bool hasFile = true;
            List<ProjectFileViewModel> currentDirectory = RootFiles.ToList();

            for(int i = 0; i < files.Count() && hasFile; i++)
            {
                hasFile = currentDirectory.Select(f => f.FileName).Contains(files[i]);
                if(hasFile)
                    currentDirectory = GetFileFromDirectory(currentDirectory, files[i]).Children.ToList();
            }

            return hasFile;
        }

        public ProjectFileViewModel GetFile(string[] pathFiles)
        {
            ProjectFileViewModel projectFileViewModel = null;
            List<ProjectFileViewModel> currentDirectory = RootFiles.ToList();
            for(int i = 0; i < pathFiles.Count() - 1; i++)
            {
                currentDirectory = GetFileFromDirectory(currentDirectory, pathFiles[i]).Children.ToList();
            }

            if(pathFiles.Any())
                projectFileViewModel = GetFileFromDirectory(currentDirectory, pathFiles[pathFiles.Count() - 1]);

            return projectFileViewModel;
        }

        public ProjectFileViewModel GetFileFromDirectory(List<ProjectFileViewModel> directory, string fileNameSearch)
        {
            return directory.Select(f => f).FirstOrDefault(f => f.FileName == fileNameSearch);
        }

        public void AddFileToParentDirectory(ProjectFile file)
        {
            if(file != null)
            {
                var pathFiles = file.Path.Replace(_rootDirectory, "").Split(new []{"\\"}, StringSplitOptions.RemoveEmptyEntries);
                var parentFile = GetFile(pathFiles.Take(pathFiles.Count() - 1).ToArray());

                if(parentFile != null)
                    parentFile.AddToChildren(file);
                else
                    AddToRoot(file);
            }

        }

        public void RemoveFileFromParentDirectory(string path)
        {
            
            var pathFiles = path.Replace(_rootDirectory,"").Split(new []{"\\"}, StringSplitOptions.RemoveEmptyEntries);

                var parentFile = GetFile(pathFiles.Take(pathFiles.Count() - 1).ToArray());

                if(parentFile != null)
                {
                    var fileToRemove = parentFile.Children.Select(f => f).First(f => f.FileName == pathFiles[pathFiles.Count() - 1]);
                    parentFile.RemoveFromChildren(fileToRemove);
                }  
                else
                {
                    var fileToRemove = RootFiles.Select(f => f).FirstOrDefault(f => f.FileName == pathFiles[pathFiles.Count() - 1]);
                   RemoveFromRoot(fileToRemove); 
                }

                
        }

        public void RenameFile(string oldPath, string newPath)
        {
            var pathFiles = oldPath.Replace(_rootDirectory, "").Split(new[] {"\\"}, StringSplitOptions.RemoveEmptyEntries);
            var fileToRename = GetFile(pathFiles.ToArray());
            if(fileToRename != null && !GetFileNameWithoutExtension(newPath).Contains("~"))
            {
                fileToRename.Path = newPath;
                fileToRename.Name = GetFileNameWithoutExtension(newPath);
            }

        }

        private string GetFileNameWithoutExtension(string path)
        {
            var file = path.Split(new[] {"\\"}, StringSplitOptions.RemoveEmptyEntries).Last();
            var parts = Regex.Split(file, "\\.");

            var name = parts[0];
            for(int i = 1; i < parts.Count() -1; i++)
            {
                name += parts[i];
            }                                   

            return name;
        }

        public void AddToRoot(ProjectFile file)
        {
            _modelFiles.Add(file);
            var fileViewModel = new ProjectFileViewModel(file);
            RootFiles.Add(fileViewModel);
            RaisePropertyChanged("RootFiles");
        }

        public void RemoveFromRoot(ProjectFileViewModel file)
        {
            if(file != null)
            {
                var fileToRemove = _modelFiles.Select(f => f).First(f => f.FileName == file.FileName);
                _modelFiles.Remove(fileToRemove);
                var fileModelToRemove = RootFiles.Select(p => p).First(p => p.FileName == file.FileName);
                RootFiles.Remove(fileModelToRemove);
                RaisePropertyChanged("Children");  
            }

        }

        public List<ProjectFileViewModel> IgnoreChildrenOfSelectedParents(List<ProjectFileViewModel> files)
        {
            var newSelectedFilesList = new List<ProjectFileViewModel>(files);
            var directories = files.Select(f => f).Where(f => f.IsDirectory).ToList();

            for (int i = 0; i < directories.Count(); i++)
                newSelectedFilesList.RemoveAll(p => p.Path.Contains(directories[i].Path + "\\"));

            return newSelectedFilesList;
        }

        public ObservableCollection<ProjectFileViewModel> GetAllFilesAsList(List<ProjectFileViewModel> parent = null )
        {
            if(parent == null)
                parent = RootFiles.ToList();

            var fileList = new ObservableCollection<ProjectFileViewModel>();

            foreach (var file in parent)
            {
                fileList.Add(file);
                if(file.IsDirectory)
                    fileList.ToList().AddRange(GetAllFilesAsList(file.Children.ToList()));
            }

            return fileList;
        }
    }
}
